# -*- coding: utf-8 -*-
# @Time    : 2021/3/11 10:26
# @Author  : zcn
# @Software: PyCharm
import json

from fastapi import APIRouter
from re_common.baselibrary.utils.basedict import BaseDicts
from re_common.baselibrary.utils.core.mlamada import bools_string

from apps.allsubdb.proxies_control.models import PostProxy, ProxiesSignal
from apps.core.global_model import InputPlatformModel
from apps.core.m_route import ContextIncludedRoute
from apps.core.return_info import InputInfoModel, ReturnInfo, FAILED, SUCCESS
from apps.sql_app.database import proxys_sql_conn
from aioredis import Redis

from apps.sql_app.redis import get_redis_pool

router = APIRouter(route_class=ContextIncludedRoute)


###############################################################################################################
# 函数区
###############################################################################################################

async def sql_select():
    # 取现有活跃代理
    sql = "select proxy from proxyall where stat = 1"
    sql_as = "select proxy from proxy_management group by proxy"
    from main import app
    pool = app.state.pool
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(sql)
            rows = await cur.fetchall()

    proxy_list = [row[0] for row in rows]

    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(sql_as)
            rows_as = await cur.fetchall()

    proxy_list_as = [row_as[0] for row_as in rows_as]
    return proxy_list, proxy_list_as


async def merge_pxoxy():
    delete_list = list()
    sql_insert = "insert ignore into proxy_management(proxy, task_name, task_tag) Values(%s, 'noname', 'noname')"
    sql_delete = "delete from proxy_management where proxy = %s and task_name = 'noname'"
    proxy_row, own_proxy_row = await sql_select()
    from main import app
    pool = app.state.pool
    # 删除 不存在IP以及为noname的
    if len(own_proxy_row) != 0:
        for proxy in own_proxy_row:
            async with pool.acquire() as conn:
                async with conn.cursor() as cur:
                    if proxy not in proxy_row:
                        await cur.execute(sql_delete, (proxy))
                        await conn.commit()
                        delete_list.append(proxy)
    # 插入新的IP
    for proxy_get in proxy_row:
        async with pool.acquire() as conn:
            async with conn.cursor() as cur:
                await cur.execute(sql_insert, (proxy_get))
                await conn.commit()

    return delete_list


async def delete_data(slist):
    sql_clean = "delete from proxy_management where proxy = %s"

    from main import app
    pool = app.state.pool
    for value in slist:
        async with pool.acquire() as conn:
            async with conn.cursor() as cur:
                await cur.execute(sql_clean, (value))
                await conn.commit()
    return True

async def update_counts():
    sql_update = "update proxy_management set counts = 0"
    from main import app
    pool = app.state.pool

    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(sql_update)
            await conn.commit()
    return True


async def sql_select_as():
    # 在自检表内取代理列表
    sql = "select proxy from proxy_management where task_name = 'noname'"
    from main import app
    pool = app.state.pool
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(sql)
            rows = await cur.fetchall()
    row_list = [row[0] for row in rows]
    return row_list


async def sql_update_noname(proxy):
    # 更新代理标识为了获得更新时间方便后期取用
    sql_as = "update proxy_management set counts = counts+1 where proxy = %s and task_name = 'noname'"
    from main import app
    pool = app.state.pool
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(sql_as, (proxy))
            await conn.commit()


async def sql_update(proxy, TKname, SPname):
    # 更新自检表 前一个更新次数方便控制, 后一个更新代理标识为了获得更新时间方便后期取用
    sql = "update proxy_management set counts = counts+1 where proxy = %s and task_name = %s and task_tag = %s"
    # sql_as = "update proxy_management set counts = counts+1 where proxy = '{}' and task_name = 'noname'".format(proxy)
    from main import app
    pool = app.state.pool
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(sql, (proxy, TKname, SPname))
            await conn.commit()

# async def proxy_times_ctrl(TKname, SPname):
#     # 根据传入的task_name和task_tag进行查询  获取代理控制次数
#     sql = f"select proxy_ctrl from taskinfo_save_setting where task_name = '{TKname}' and task_tag = '{SPname}'"
#     # sql_as = "update proxy_management set counts = counts+1 where proxy = '{}' and task_name = 'noname'".format(proxy)
#     from main import app
#     pool = app.state.pool
#     async with pool.acquire() as conn:
#         async with conn.cursor() as cur:
#             proxy_count = await cur.fetchone(sql)
#             await conn.commit()
#     return proxy_count[0]

async def proxy_times_ctrl(TKname, SPname):
    # 根据传入的task_name和task_tag进行查询  获取代理控制次数
    from main import app
    redis = app.state.redis
    _id = "_".join([TKname, SPname])
    if _id != "chaoxing_cookie_cx_cookie":
        taskinfo_save_setting = await redis.hget("taskinfo_save_setting", _id)
        if not taskinfo_save_setting:
            raise Exception("不能获取代理, 因为输入参数错误: ", _id)
        data = json.loads(taskinfo_save_setting)
        proxy_count = BaseDicts.is_dict_exit_key(data, "proxy_ctrl", default=3)
    else:
        proxy_count = 3
    return proxy_count


###############################################################################################################
# API区
###############################################################################################################


@router.get("/proxyupdate/proxies_management")
async def get_proxy():
    return_info = ReturnInfo()
    delete_list = await merge_pxoxy()
    bools = await delete_data(delete_list)
    if bools:
        return_info.status = SUCCESS
        return_info.msg_code = 200
        return_info.msg = "代理获取成功"
        return_info.data = delete_list
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg_code = 200
        return_info.msg = "代理更新失败"
        return_info.data = ''
        return return_info.todict()

@router.get("/proxyupdate/proxies_update")
async def get_proxy():
    from main import app
    return_info = ReturnInfo()
    bools = await update_counts()
    if not hasattr(app.state, "proxy_dict"):
        app.state.proxy_dict = dict()
    app.state.proxy_list = await sql_select_as()
    for key, value in app.state.proxy_dict.items():
        proxy_list = app.state.proxy_list.copy()
        app.state.proxy_dict[key] = proxy_list
    if bools:
        return_info.status = SUCCESS
        return_info.msg_code = 200
        return_info.msg = "代理更新成功"
        return_info.data = ''
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg_code = 200
        return_info.msg = "代理更新失败"
        return_info.data = ''
        return return_info.todict()


@router.get("/getproxy/secret_proxy")
async def journal_list():
    """
    获取私密代理
    marks: lblPageCount
    :param input:
    :return:
    """
    return_info = ReturnInfo()
    sql = "select proxy from proxyall where stat=1"
    rows = await proxys_sql_conn.fetch_all(query=sql)
    result = [row[0] for row in rows]

    return_info.status = bools_string(True)
    return_info.msg_code = 200
    return_info.msg = ""
    return_info.data = result
    return return_info.todict()

@router.get("/getproxy/random_one")
async def journal_list():
    """
    随机获取一个私密代理
    marks: lblPageCount
    :param input:
    :return:
    """
    return_info = ReturnInfo()
    sql = "select proxy from proxyall where stat = 1 order by rand() limit 1"
    rows = await proxys_sql_conn.fetch_all(query=sql)
    result = rows[0]

    return_info.status = bools_string(True)
    return_info.msg_code = 200
    return_info.msg = ""
    return_info.data = result
    return return_info.todict()



    # await proxys_sql_conn.execute(query=sql_as)


# @router.post("/proxies_get/get_one")
# async def get_proxy(input: InputPlatformModel[PostProxy]):
#     from main import app
#     return_info = ReturnInfo()
#     task_name = input.data.task_name
#     task_tag = input.data.task_tag
#     proxies_list = await sql_select_as()
#     sql_check = "select counts from proxy_management where proxy = %s and task_name = %s and task_tag = %s"
#
#     sql_insert = "insert ignore into proxy_management(proxy, task_name, task_tag) Values(%s, %s, %s)"
#
#     for proxy in proxies_list:
#         await sql_update_noname(proxy)
#         pool = app.state.pool
#         async with pool.acquire() as conn:
#             async with conn.cursor() as cur:
#                 await cur.execute(sql_check, (proxy, task_name, task_tag))
#                 row_check = await cur.fetchone()
#                 await conn.commit()
#         if row_check is None:
#             async with pool.acquire() as conn:
#                 async with conn.cursor() as cur:
#                     await cur.execute(sql_insert, (proxy, task_name, task_tag))
#                     await conn.commit()
#             return_info.status = SUCCESS
#             return_info.msg_code = 200
#             return_info.msg = "代理获取成功"
#             return_info.data = proxy
#             return return_info.todict()
#         elif row_check[0] < 3:
#             await sql_update(proxy, task_name, task_tag)
#             return_info.status = SUCCESS
#             return_info.msg_code = 200
#             return_info.msg = "代理获取成功"
#             return_info.data = proxy
#             return return_info.todict()
#     return_info.status = FAILED
#     return_info.msg_code = 200
#     return_info.msg = "现在时间段所有代理使用已达到阈值"
#     return_info.data = ''
#     return return_info.todict()


@router.post("/proxies_get/get_one")
async def get_proxy(input: InputPlatformModel[PostProxy]):
    sql_check = "select counts from proxy_management where proxy = %s and task_name = %s and task_tag = %s"
    sql_insert = "insert ignore into proxy_management(proxy, task_name, task_tag) Values(%s, %s, %s)"
    from main import app
    pool = app.state.pool
    return_info = ReturnInfo()
    task_name = input.data.task_name
    task_tag = input.data.task_tag
    # max_proxy_get = input.data.max_proxy_get
    max_proxy_get = await proxy_times_ctrl(task_name, task_tag)
    key = "_".join([task_name, task_tag])
    if not hasattr(app.state, "proxy_dict"):
        app.state.proxy_dict = dict()
    if hasattr(app.state, "proxy_list"):
        proxy_list = BaseDicts.is_dict_exit_key(app.state.proxy_dict, key, default=[])
        if not proxy_list:
            proxy_list_whole = app.state.proxy_list.copy()
            app.state.proxy_dict[key] = proxy_list_whole
            proxy_list = BaseDicts.is_dict_exit_key(app.state.proxy_dict, key, default=[])
        try:
            while True:
                proxy = proxy_list.pop()
                async with pool.acquire() as conn:
                    async with conn.cursor() as cur:
                        await cur.execute(sql_check, (proxy, task_name, task_tag))
                        row_check = await cur.fetchone()
                        await conn.commit()
                if row_check is None:
                    async with pool.acquire() as conn:
                        async with conn.cursor() as cur:
                            await cur.execute(sql_insert, (proxy, task_name, task_tag))
                            await conn.commit()
                    return_info.status = SUCCESS
                    return_info.msg_code = 200
                    return_info.msg = "代理获取成功"
                    return_info.data = proxy
                    return return_info.todict()
                elif row_check[0] < max_proxy_get:
                    await sql_update(proxy, task_name, task_tag)
                    return_info.status = SUCCESS
                    return_info.msg_code = 200
                    return_info.msg = "代理获取成功"
                    return_info.data = proxy
                    return return_info.todict()
                else:
                    return_info.status = FAILED
                    return_info.msg_code = 230
                    return_info.msg = "代理次数在当前时间段内已取光,请稍候重试"
                    return_info.data = ""
                    return return_info.todict()

        except IndexError:
            if not hasattr(app.state, "proxy_judge") or app.state.proxy_judge is not True:
                app.state.proxy_judge = True
                try:
                    app.state.proxy_dict[key].extend(app.state.proxy_list)
                except:
                    app.state.proxy_judge = False
                finally:
                    app.state.proxy_judge = False
                    return_info.status = FAILED
                    return_info.msg_code = 231
                    return_info.msg = "正在处理全局列表中,请稍候重试"
                    return_info.data = ""
                    return return_info.todict()
            else:
                return_info.status = FAILED
                return_info.msg_code = 232
                return_info.msg = "正在处理全局列表中,请稍候重试"
                return_info.data = ""
                return return_info.todict()
    else:
        app.state.proxy_list = await sql_select_as()
        return_info.status = FAILED
        return_info.msg_code = 233
        return_info.msg = "正在处理全局列表中,请稍候重试"
        return_info.data = ""
        return return_info.todict()

